#pragma once

#include <utility>
#include <memory>
#include <filesystem>
#include "helper/resource/ReopenableResource.h"
#include "helper/iter/Iterator.h"

namespace helper {
namespace sqlite {
	class IDB;
	class Statement;
	class QueryResult;
}//namespace sqlite
}//namespace helper

namespace memdb {
namespace impl {
namespace simple {

class KvTable : public helper::resource::ReopenableResource<std::error_code>{
public:
  KvTable(const std::filesystem::path & parent, const std::string & name);
  ~KvTable() override;

public:
  std::error_code destroy() override;
  bool exists() const override;

	inline const std::string & name() const{
		return _name;
	}



  inline std::error_code TEST_createTable() {
    return createTable();
  }
  inline bool TEST_existsTable() const {
    return existsTable();
  }
  inline std::error_code TEST_dropTable() {
    return dropTable();
  }
protected:
  std::error_code _open() override ;
  std::error_code _close() override;

  std::error_code create();
  std::error_code openExists();


private: //impl
	std::error_code createTable();
	bool existsTable() const;
  std::error_code dropTable();


//Records related
public:
	class Records { //TODO: extract an interface IRecords ?
	public:
		explicit Records(KvTable & table);
		~Records();
		// dml
		std::error_code insert(const std::string & key, const std::string & value);
		std::error_code remove(const std::string & key);
		std::error_code update(const std::string & key, const std::string & value);//only update 

		std::error_code replace(const std::string & key, const std::string & value);

		// dql
		bool exists(const std::string & key) const;
		std::error_code get(const std::string & key, std::string & value) const;

		size_t count() const;

		// iterator 
		typedef std::pair<const std::string, std::string> * Item;
		std::unique_ptr<helper::iter::Iterator<Item>> iterator() const;
		std::unique_ptr<helper::iter::Iterator<Item>> iterator(size_t offset, size_t len) const;
		std::unique_ptr<helper::iter::Iterator<Item>> iterator(const std::string & key, size_t offset, size_t len) const;
	private:
		KvTable & _table;
	};

	Records & records() const ;

public:
	const helper::sqlite::IDB & _handle() const {
		return *_db;
	}

private:
  std::string _name;
	std::filesystem::path _dir;
  std::filesystem::path _filePath;// table file whole path
															//
	std::unique_ptr<helper::sqlite::IDB> _db;
	std::unique_ptr<Records> _records;

	friend class Records;
};


}//namespace simple
}//namespace impl
}//namespace memdb
